package com.jfinal.plugin.activerecord.sql;

import com.alibaba.fastjson.JSON;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * SQL查询
 *
 * @author Chen
 * @date 15/5/26
 */

public class SqlSelect extends SqlObject<SqlSelect> {

    public static final String SELECT = " SELECT ";

    public static final String FROM = " FROM ";

    public static final String LEFT_JOIN = " LEFT JOIN ";
    public static final String RIGHT_JOIN = " RIGHT JOIN ";

    public static final String ON = " ON ";

    protected List<Object> params = new ArrayList<>();

    protected List<String> columns = new ArrayList<>();

    private String sqlJoin = "";

    public SqlSelect columns(String columns) {
        this.columns.clear();
        this.columns.addAll(Arrays.asList(columns.split(",")));
        return this;
    }

    public SqlSelect addColumn(String column) {
        this.columns.add(column);
        return this;
    }

    private SqlSelect tableName(String tableName) {
        this.tableName = tableName;
        return this;
    }

    public SqlSelect from(String tableName) {
        return this.tableName(tableName);
    }

    public SqlSelect from(String tableName, String alias) {
        return this.tableName(tableName + " " + alias);
    }

    public SqlSelect from(SqlSelect sqlSelect, String alias) {
        this.tableName = "(" + sqlSelect.toSql() + ") " + alias;
        this.params.addAll(Arrays.asList(sqlSelect.getParams()));
        return this;
    }


    public SqlSelect join(String join) {
        this.sqlJoin += " " + join;
        return this;
    }

    public SqlSelect leftJoin(String tableName, String on) {
        return leftJoin(tableName, "", on);
    }

    public SqlSelect leftJoin(String tableName, String alias, String on) {
        String table = tableName + " " + alias;
        if (!this.sqlJoin.contains(table)) {
            this.sqlJoin += LEFT_JOIN + table + ON + on;
        }
        return this;
    }

    public SqlSelect leftJoin(SqlSelect sqlSelect, String alias, String on) {
        this.sqlJoin += LEFT_JOIN + "(" + sqlSelect.toSql() + ") " + alias + ON + on;
        this.params.addAll(Arrays.asList(sqlSelect.getParams()));
        return this;
    }

    public SqlSelect rightJoin(String tableName, String on) {
        return this.rightJoin(tableName, "", on);
    }

    public SqlSelect rightJoin(String tableName, String alias, String on) {
        String table = tableName + " " + alias;
        if (!this.sqlJoin.contains(table)) {
            this.sqlJoin += RIGHT_JOIN + table + ON + on;
        }
        return this;
    }

    public SqlSelect rightJoin(SqlSelect sqlSelect, String alias, String on) {
        this.sqlJoin += RIGHT_JOIN + "(" + sqlSelect.toSql() + ") " + alias + ON + on;
        this.params.addAll(Arrays.asList(sqlSelect.getParams()));
        return this;
    }


    @Override
    public Object[] getParams() {
        List<Object> params = new ArrayList<>();
        params.addAll(this.params);
        params.addAll(Arrays.asList(this.spec.getParams()));
        return params.toArray();
    }


    @Override
    public String toSql() {
        return new StringBuilder(getSelectSql()).append(getSpecSql()).toString();
    }

    public String getSelectSql() {
        return SELECT + (columns.isEmpty() ? "*" : String.join(",", columns));
    }

    @Override
    public String getSpecSql() {
        return FROM + tableName + sqlJoin + super.getSpecSql();
    }

    @Override
    public String getExceptSql() {
        return FROM + tableName + sqlJoin + super.getExceptSql();
    }

    public String getSummarySql() {
        return new StringBuilder(getSelectSql()).append(FROM + tableName + sqlJoin + super.getWhereSql()).toString();
    }

    public static void main(String[] args) {

        SqlSelect sql1 = Sql.select("a,b,c").addColumn("d,f")
                .from("user u ")
                .where(Spec.where("age", ">", 1).and("name=?", "cjk"));

        SqlSelect sqlSelect = Sql.select("a,b,c").addColumn("d,f").from("user u ")
                .leftJoin(sql1, "a", "u.id = a.id")
                .leftJoin("class c", "u.id = c.id")
                .leftJoin("student s", "u.id = s.id")
                .where(Spec.where("age", ">", 3).limit(10).desc("age"));


        System.out.println(sqlSelect.toSql());
        System.out.println(JSON.toJSONString(sqlSelect.getParams()));

        SqlSelect sqlSelect3 = Sql.select("a,b,c")
                .addColumn("d,f")
                .from(sql1,"ss")
                .leftJoin(sql1, "a", "u.id = a.id")
                .leftJoin("class c", "u.id = c.id")
                .leftJoin("student s", "u.id = s.id")
                .where(Spec.where("age", ">", 3).limit(10).desc("age"));

        System.out.println(sqlSelect3.toSql());
        System.out.println(JSON.toJSONString(sqlSelect3.getParams()));
        System.out.println(sqlSelect3.getSummarySql());
    }

}
